home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / MNetsrc.hqx / Mac TCP_IP Source v.33 / ax25cmd.c < prev    next >
C/C++ Source or Header  |  1989-04-03  |  14KB  |  669 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "ax25.h"
  5. #include "ax_mbx.h"
  6. #include "timer.h"
  7. #include "iface.h"
  8. #include "lapb.h"
  9. #include "cmdparse.h"
  10. #include "session.h"
  11. #ifdef MAC
  12. #include "unix.h"
  13. #include "heard.h"
  14. #endif
  15.  
  16. char *ax25states[] = {
  17.     "Disconnected",
  18.     "Conn pending",
  19.     "Disc pending",
  20.     "Connected",
  21.     "Recovery",
  22.     "Frame Reject",
  23. };
  24.  
  25. int domycall(),dodigipeat(),doaxstat(),dot1(),dot2(),dot3(),domaxframe(),
  26. #ifdef MAC
  27.     doaxwindow(),dopaclen(),don2(),doaxreset(),dopthresh(),doheard();
  28. #else
  29.     doaxwindow(),dopaclen(),don2(),doaxreset(),dopthresh();
  30. #endif
  31.  
  32. static struct cmds axcmds[] = {
  33.     "digipeat",    dodigipeat,    0, NULLCHAR,    NULLCHAR,
  34.     "maxframe",    domaxframe,    0, NULLCHAR,    NULLCHAR,
  35.     "mycall",    domycall,    0, NULLCHAR,    NULLCHAR,
  36.     "paclen",    dopaclen,    0, NULLCHAR,    NULLCHAR,
  37.     "pthresh",    dopthresh,    0, NULLCHAR,    NULLCHAR,
  38.     "reset",    doaxreset,    2, "ax25 reset <axcb>", NULLCHAR,
  39.     "retry",    don2,        0, NULLCHAR,    NULLCHAR,
  40.     "status",    doaxstat,    0, NULLCHAR,    NULLCHAR,
  41.     "t1",        dot1,        0, NULLCHAR,    NULLCHAR,
  42.     "t2",        dot2,        0, NULLCHAR,    NULLCHAR,
  43.     "t3",        dot3,        0, NULLCHAR,    NULLCHAR,
  44.     "window",    doaxwindow,    0, NULLCHAR,    NULLCHAR,
  45. #ifdef MAC
  46.     "heard",    doheard,    0, NULLCHAR,    NULLCHAR,
  47.     NULLCHAR,    NULLFP,        0, "ax25 subcommands: digipeat heard maxframe mycall paclen pthresh reset retry status\n\tt1 t2 t3 window",    NULLCHAR,
  48. #else
  49.     NULLCHAR,    NULLFP,        0, "ax25 subcommands: digipeat maxframe mycall paclen pthresh reset retry status\n\tt1 t2 t3 window",    NULLCHAR,
  50. #endif
  51. };
  52. /* Multiplexer for top-level ax25 command */
  53. doax25(argc,argv)
  54. int argc;
  55. char *argv[];
  56. {
  57.     return subcmd(axcmds,argc,argv);
  58. }
  59.  
  60. static
  61. doaxreset(argc,argv)
  62. int argc;
  63. char *argv[];
  64. {
  65.     struct ax25_cb *axp;
  66.     extern char notval[];
  67.  
  68.     axp = (struct ax25_cb *)htol(argv[1]);
  69.     if(!ax25val(axp)){
  70.         printf(notval);
  71.         return 1;
  72.     }
  73.     reset_ax25(axp);
  74.     return 0;
  75. }
  76.  
  77. /* Display AX.25 link level control blocks */
  78. static
  79. doaxstat(argc,argv)
  80. int argc;
  81. char *argv[];
  82. {
  83.     register int i;
  84.     register struct ax25_cb *axp;
  85.     char tmp[10];
  86.     extern char notval[];
  87.  
  88.     if(argc < 2){
  89.         printf("    &AXB IF   Snd-Q   Rcv-Q   Remote    State\n");
  90.         for(i=0;i<NHASH;i++){
  91.             for(axp = ax25_cb[i];axp != NULLAX25; axp = axp->next){
  92.                 pax25(tmp,&axp->addr.dest);
  93.                 printf("%8lx %-5s%-8d%-8d%-10s%s\n",
  94.                     (long)axp,axp->interface->name,
  95.                     len_q(axp->txq),len_mbuf(axp->rxq),
  96.                     tmp,ax25states[axp->state]);
  97.             }
  98.         }
  99.         return 0;
  100.     }
  101.     axp = (struct ax25_cb *)htol(argv[1]);
  102.     if(!ax25val(axp)){
  103.         printf(notval);
  104.         return 1;
  105.     }
  106.     dumpstat(axp);
  107.     return 0;
  108. }
  109. /* Dump one control block */
  110. static
  111. dumpstat(axp)
  112. register struct ax25_cb *axp;
  113. {
  114.     char tmp[10];
  115.     int i;
  116.  
  117.     if(axp == NULLAX25 || axp->interface == NULLIF)
  118.         return;
  119.     printf("&AXB IF   Remote   RB V(S) V(R) Unack P Retry State\n");
  120.     pax25(tmp,&axp->addr.dest);
  121.     printf("%4x %-5s%-9s",(int)axp,axp->interface->name,tmp);
  122.     putchar(axp->rejsent ? 'R' : ' ');
  123.     putchar(axp->remotebusy ? 'B' : ' ');
  124.     printf(" %4d %4d",axp->vs,axp->vr);
  125.     printf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  126.     printf(" %02u/%02u",axp->retries,axp->n2);
  127.     printf(" %s\n",ax25states[axp->state]);
  128.  
  129.     printf("T1: ");
  130.     if(run_timer(&axp->t1))
  131.         printf("%lu",(axp->t1.start - axp->t1.count) * MSPTICK);
  132.     else
  133.         printf("stop");
  134.     printf("/%lu ms; ",axp->t1.start * MSPTICK);
  135.  
  136.     printf("T2: ");
  137.     if(run_timer(&axp->t2))
  138.         printf("%lu",(axp->t2.start - axp->t2.count) * MSPTICK);
  139.     else
  140.         printf("stop");
  141.     printf("/%lu ms; ",axp->t2.start * MSPTICK);
  142.  
  143.     printf("T3: ");
  144.     if(run_timer(&axp->t3))
  145.         printf("%lu",(axp->t3.start - axp->t3.count) * MSPTICK);
  146.     else
  147.         printf("stop");
  148.     printf("/%lu ms\n",axp->t3.start * MSPTICK);
  149.  
  150.     if(axp->addr.ndigis == 0)
  151.         return;
  152.     printf("Digipeaters:");
  153.     for(i=0;i<axp->addr.ndigis;i++){
  154.         pax25(tmp,&axp->addr.digis[i]);
  155.         printf(" %s",tmp);
  156.     }
  157.     printf("\n");
  158. }
  159.  
  160. /* Display or change our AX.25 address */
  161. static
  162. domycall(argc,argv)
  163. int argc;
  164. char *argv[];
  165. {
  166.     char buf[15];
  167.  
  168.     if(argc < 2){
  169.         pax25(buf,&mycall);
  170.         printf("%s\n",buf);
  171.         return 0;
  172.     }
  173.     if(setcall(&mycall,argv[1]) == -1)
  174.         return -1;
  175.     mycall.ssid |= E;
  176.     return 0;
  177. }
  178.  
  179. /* Control AX.25 digipeating */
  180. static
  181. dodigipeat(argc,argv)
  182. int argc;
  183. char *argv[];
  184. {
  185.     extern int digipeat;
  186.  
  187.     if(argc == 1) {
  188.         printf("digipeat %s\n",digipeat ? "on" : "off");
  189.     } else {
  190.         if(strcmp(argv[1],"on") == 0)
  191.             digipeat = 1;
  192.         else
  193.             digipeat = 0;
  194.     }
  195. }
  196.  
  197. /* Set retransmission timer */
  198. static
  199. dot1(argc,argv)
  200. int argc;
  201. char *argv[];
  202. {
  203.     extern int16 t1init;
  204.  
  205.     if(argc == 1) {
  206.         printf("T1 %lu ms\n",(long)t1init * MSPTICK);
  207.     } else {
  208.         t1init = atol(argv[1]) / MSPTICK;
  209.     }
  210. }
  211.  
  212. /* Set acknowledgement delay timer */
  213. static
  214. dot2(argc,argv)
  215. int argc;
  216. char *argv[];
  217. {
  218.     extern int16 t2init;
  219.  
  220.     if(argc == 1) {
  221.         printf("T2 %lu ms\n",(long)t2init * MSPTICK);
  222.     } else {
  223.         t2init = atol(argv[1]) / MSPTICK;
  224.     }
  225. }
  226.  
  227. /* Set idle timer */
  228. static
  229. dot3(argc,argv)
  230. int argc;
  231. char *argv[];
  232. {
  233.     extern int16 t3init;
  234.  
  235.     if(argc == 1) {
  236.         printf("T3 %lu ms\n",(long)t3init * MSPTICK);
  237.     } else {
  238.         t3init = atol(argv[1]) / MSPTICK;
  239.     }
  240. }
  241.  
  242. /* Set retry limit count */
  243. static
  244. don2(argc,argv)
  245. int argc;
  246. char *argv[];
  247. {
  248.     extern int16 n2;
  249.  
  250.     if(argc == 1) {
  251.         printf("Retry %u\n",n2);
  252.     } else {
  253.         n2 = atoi(argv[1]);
  254.     }
  255. }
  256.  
  257. /* Set maximum number of frames that will be allowed in flight */
  258. static
  259. domaxframe(argc,argv)
  260. int argc;
  261. char *argv[];
  262. {
  263.     extern int16 maxframe;
  264.  
  265.     if(argc == 1) {
  266.         printf("Maxframe %u\n",maxframe);
  267.     } else {
  268.         maxframe = atoi(argv[1]);
  269.     }
  270. }
  271.  
  272. /* Set maximum length of I-frame data field */
  273. static
  274. dopaclen(argc,argv)
  275. int argc;
  276. char *argv[];
  277. {
  278.     extern int16 paclen;
  279.  
  280.     if(argc == 1) {
  281.         printf("Paclen %u\n",paclen);
  282.     } else {
  283.         paclen = atoi(argv[1]);
  284.     }
  285. }
  286. /* Set size of I-frame above which polls will be sent after a timeout */
  287. static
  288. dopthresh(argc,argv)
  289. int argc;
  290. char *argv[];
  291. {
  292.     extern int16 pthresh;
  293.  
  294.     if(argc == 1) {
  295.         printf("Pthresh %u\n",pthresh);
  296.     } else {
  297.         pthresh = atoi(argv[1]);
  298.     }
  299. }
  300.  
  301. /* Set high water mark on receive queue that triggers RNR */
  302. static
  303. doaxwindow(argc,argv)
  304. int argc;
  305. char *argv[];
  306. {
  307.     extern int16 axwindow;
  308.  
  309.     if(argc == 1) {
  310.         printf("Axwindow %u\n",axwindow);
  311.     } else {
  312.         axwindow = atoi(argv[1]);
  313.     }
  314. }
  315. /* End of ax25 subcommands */
  316.  
  317. /* Initiate interactive AX.25 connect to remote station */
  318. doconnect(argc,argv)
  319. int argc;
  320. char *argv[];
  321.  {
  322.     void ax_rx(),ax_tx(),ax_state();
  323.     int ax_parse();
  324.     struct ax25_addr dest;
  325.     struct ax25 addr;
  326.     struct ax25_cb *open_ax25();
  327.     struct interface *ifp;
  328.     struct session *s;
  329.     extern int16 axwindow;
  330.     int i;
  331.  
  332.     if (strcmp(argv[1],"netrom") == 0) {
  333.         printf("Connect on netrom interface not supported\n") ;
  334.         return 1 ;
  335.     }
  336.     
  337.     for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  338.         if(strcmp(argv[1],ifp->name) == 0)
  339.             break;
  340.  
  341.     if(ifp == NULLIF){
  342.         printf("Interface %s unknown\n",argv[1]);
  343.         return 1;
  344.     }
  345.     setcall(&dest,argv[2]);
  346.     /* See if a session already exists */
  347.     for(s = sessions; s < &sessions[nsessions]; s++){
  348.         if(s->type == AX25TNC
  349.          && addreq(&s->cb.ax25_cb->addr.dest,&dest)){
  350. #if    (defined(MAC) || defined(AMIGA))
  351.             printf("Session %lu to %s already exists\n",
  352. #else
  353.             printf("Session %u to %s already exists\n",
  354. #endif
  355.                 s - sessions,argv[2]);
  356.             return 1;
  357.         }
  358.     }
  359.     /* Allocate a session descriptor */
  360.     if((s = newsession()) == NULLSESSION){
  361.         printf("Too many sessions\n");
  362.         return 1;
  363.     }
  364.     if((s->name = malloc((unsigned)strlen(argv[2])+1)) != NULLCHAR)
  365.         strcpy(s->name,argv[2]);
  366.     s->type = AX25TNC;
  367.     s->parse = ax_parse;
  368.     current = s;
  369.     ASSIGN(addr.source,mycall);
  370.     setcall(&addr.dest,argv[2]);
  371.     for(i=3; i < argc; i++)
  372.         setcall(&addr.digis[i-3],argv[i]);
  373.  
  374.     addr.ndigis = i - 3;
  375.     s->cb.ax25_cb = open_ax25(&addr,axwindow,ax_rx,ax_tx,ax_state,ifp,(char *)s);
  376.     go();
  377.     return 0;
  378. }
  379.  
  380.  
  381. /* Display changes in AX.25 state */
  382. void
  383. ax_state(axp,old,new)
  384. struct ax25_cb *axp;
  385. int old,new;
  386. {
  387.     struct session *s;
  388.  
  389.     s = (struct session *)axp->user;
  390.  
  391.     if(current != NULLSESSION && current->type == AX25TNC && current == s){
  392.         /* Don't print transitions between CONNECTED and RECOVERY */
  393.         if(new != RECOVERY && !(old == RECOVERY && new == CONNECTED))
  394.             printf("%s\n",ax25states[new]);
  395.         if(new == DISCONNECTED)
  396.             cmdmode();
  397.         fflush(stdout);
  398.     }
  399.     if(new == DISCONNECTED){
  400.         axp->user = NULLCHAR;
  401.         freesession(s);
  402.     }
  403. }
  404. /* Handle typed characters on AX.25 connection */
  405. int
  406. ax_parse(buf,cnt)
  407. char *buf;
  408. int16 cnt;
  409. {
  410.     struct mbuf *bp;
  411.     register char *cp;
  412.     char c;
  413.  
  414.     if(current == NULLSESSION || current->type != AX25TNC)
  415.         return;    /* "can't happen" */
  416.  
  417.     /* If recording is on, record outgoing stuff too */
  418. #ifdef MAC
  419.     if(current->record != NULLFILE) {
  420.         fwrite(buf,1,cnt-1,current->record);
  421.     }
  422. #else
  423.     if(current->record != NULLFILE)
  424.         fwrite(buf,1,cnt,current->record);
  425. #endif
  426.  
  427.     /* Allocate buffer and start it with the PID */
  428.     bp = alloc_mbuf(cnt+1);
  429.     *bp->data = PID_FIRST | PID_LAST | PID_NO_L3;
  430.     bp->cnt++;
  431.  
  432.     /* Copy keyboard buffer to output, stripping line feeds */
  433.     cp = bp->data + 1;
  434.     while(cnt-- != 0){
  435.         c = *buf++;
  436.         if(c != '\n'){
  437.             *cp++ = c;
  438.             bp->cnt++;
  439.         }
  440.     }
  441.     send_ax25(current->cb.ax25_cb,bp);
  442. }
  443. /* Handle new incoming terminal sessions
  444.  * This is the default receive upcall function, used when
  445.  * someone else connects to us
  446.  */
  447. void
  448. ax_incom(axp,cnt)
  449. register struct ax25_cb *axp;
  450. int16 cnt;
  451. {
  452.     void ax_session() ;
  453.     
  454.     if (ax25mbox)
  455.         mbx_incom(axp,cnt) ;
  456.     else
  457.         ax_session(axp,cnt) ;
  458.     return ;
  459.  
  460. }
  461.  
  462. /* This function sets up an ax25 chat session */
  463. void
  464. ax_session(axp,cnt)
  465. register struct ax25_cb *axp ;
  466. int16 cnt ;
  467. {
  468.     struct session *s;
  469.     char remote[10];
  470.     void ax_rx(),ax_state(),ax_tx();
  471.  
  472.     pax25(remote,&axp->addr.dest);
  473.     if((s = newsession()) == NULLSESSION){
  474.         /* Out of sessions */
  475.         disc_ax25(axp);
  476.         return;
  477.     }
  478.     s->type = AX25TNC;
  479.     s->name = malloc((int16)strlen(remote)+1);
  480.     s->cb.ax25_cb = axp;
  481.     s->parse = ax_parse;
  482.     strcpy(s->name,remote);
  483.     axp->r_upcall = ax_rx;
  484.     axp->s_upcall = ax_state;
  485.     axp->t_upcall = ax_tx;
  486.     axp->user = (char *)s;
  487. #if    (defined(MAC) || defined(AMIGA))
  488.     printf("\007Incoming AX25 session %lu from %s\n",s - sessions,remote);
  489. #else
  490.     printf("\007Incoming AX25 session %u from %s\n",s - sessions,remote);
  491. #endif
  492.     fflush(stdout);
  493. }
  494.  
  495. /* Handle incoming terminal traffic */
  496. void
  497. ax_rx(axp,cnt)
  498. struct ax25_cb *axp;
  499. int16 cnt;
  500. {
  501.     register struct mbuf *bp;
  502.     struct mbuf *recv_ax25();
  503.     char c;
  504.  
  505.     /* Hold output if we're not the current session */
  506.     if(mode != CONV_MODE || current == NULLSESSION
  507.      || current->type != AX25TNC || current->cb.ax25_cb != axp)
  508.         return;
  509.  
  510.     if((bp = recv_ax25(axp,cnt)) == NULLBUF)
  511.         return;
  512.  
  513.     /* Display received characters, translating CR's to CR/LF */
  514.     while(bp != NULLBUF){
  515.         while(bp->cnt-- != 0){
  516.             c = *bp->data++;
  517.             if(c == '\r')
  518.                 c = '\n';
  519.             putchar(c);
  520.             if(current->record){
  521. #ifndef UNIX
  522. #ifndef MAC
  523.                 if(c == '\n')
  524.                     fputc('\r',current->record);
  525. #endif
  526. #endif
  527.                 fputc(c,current->record);
  528.             }
  529.         }
  530.         bp = free_mbuf(bp);
  531.     }
  532. #ifndef MAC
  533.     if(current->record)
  534.         fflush(current->record);
  535. #endif
  536.     fflush(stdout);
  537. }
  538. /* Handle transmit upcalls. Used only for file uploading */
  539. void
  540. ax_tx(axp,cnt)
  541. struct ax25_cb *axp;
  542. int16 cnt;
  543. {
  544.     register char *cp;
  545.     struct session *s;
  546.     register struct mbuf *bp;
  547.     int16 size;
  548.     int c;
  549.  
  550.     if((s = (struct session *)axp->user) == NULLSESSION
  551.      || s->upload == NULLFILE)
  552.         return;
  553.     while(cnt != 0){
  554.         size = min(cnt,axp->paclen+1);
  555.         if((bp = alloc_mbuf(size)) == NULLBUF)
  556.             break;
  557.         cp = bp->data;
  558.         /* Start with the PID */
  559.         *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  560.         bp->cnt++;
  561.  
  562.         /* Now send data characters, translating between local
  563.          * keyboard end-of-line sequences and the (unwritten)
  564.          * AX.25 convention, which is carriage-return only
  565.          */
  566.         while(bp->cnt < size){
  567.             if((c = getc(s->upload)) == EOF)
  568.                 break;
  569. #ifdef    MSDOS
  570.             /* MS-DOS gives cr-lf */
  571.             if(c == '\n')
  572.                 continue;
  573. #endif
  574. #if    (defined(UNIX) || defined(MAC) || defined(AMIGA))
  575.             /* These give lf only */
  576.             if(c == '\n')
  577.                 c = '\r';
  578. #endif
  579.             *cp++ = c;
  580.             bp->cnt++;
  581.         }    
  582.         if(bp->cnt > 1) {
  583.             send_ax25(axp,bp);
  584.         } else {
  585.             /* Empty frame, don't bother sending */
  586.             free_p(bp);
  587.             break;
  588.         }
  589.         cnt -= bp->cnt;
  590.     }
  591.     if(cnt != 0){
  592.         /* Error or end-of-file */
  593.         fclose(s->upload);
  594.         s->upload = NULLFILE;
  595.         free(s->ufile);
  596.         s->ufile = NULLCHAR;
  597.     }
  598. }
  599.  
  600. #ifdef MAC
  601. struct ax25_heard heard = {0,0};
  602. /* Display AX.25 heard list */
  603. static
  604. doheard(argc,argv)
  605. int argc;
  606. char *argv[];
  607. {
  608.     struct heard_stuff *hp;
  609.     struct ax25_addr *dp;
  610.     extern struct ax25_heard heard;
  611.     char tmp[16];
  612.     int16 curr;
  613.  
  614.     if(argc < 2) {
  615.         if (!heard.enabled) {
  616.             printf("not enabled\n");
  617.             return(0);
  618.         }
  619.         printf("Heard list:\n");
  620.         curr = heard.first;
  621.         while (curr != -1) {
  622.             hp = &heard.list[curr];
  623.             pax25(tmp,&hp->info.source);
  624.             printf("%s",tmp);
  625.             if(hp->info.ndigis > 0){
  626.                 printf(" (via");
  627.                 /* Print digi string until packet got to us */
  628.                 for(dp = &hp->info.digis[0]; dp < &hp->info.digis[hp->info.ndigis]; dp++){
  629.                     if (dp->ssid & REPEATED) {
  630.                         pax25(tmp,dp);
  631.                         printf(" %s",tmp);
  632.                     } else {
  633.                         break;
  634.                     }
  635.                 }
  636.                 printf(")");
  637.             }
  638.             if (hp->flags) {
  639.                 printf("%s%s%s",  (hp->flags & HEARD_ARP) ? " ARP" : "",
  640.                                     (hp->flags & HEARD_NETROM) ? " NETROM" : "",
  641.                                     (hp->flags & HEARD_IP) ? " IP" : "");
  642.             }
  643.             printf("  %s", ctime(&hp->htime));
  644.             curr = hp->next;
  645.         }
  646.         return 0;
  647.     }
  648.     if (strcmp(argv[1],"clear") == 0) {
  649.         heard.cnt = 0;
  650.         heard.first = -1;
  651.         return 0;
  652.     } else if (strcmp(argv[1],"on") == 0) {
  653.         if (!heard.enabled) {
  654.             heard.enabled = 1;
  655.             heard.cnt = 0;
  656.             heard.first = -1;
  657.         }
  658.         return 0;
  659.     } else if (strcmp(argv[1],"off") == 0) {
  660.         heard.enabled = 0;
  661.         return 0;
  662.     } else {
  663.         printf("Usage: ax25 heard [ on | off | clear ]\n");
  664.     }
  665.     return 0;
  666. }
  667. #endif
  668.  
  669.